﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace NUtils
{
    // Summary:
    //     Defines a sortby/value pair that can be set or retrieved.
    //
    // Type parameters:
    //   TSort:
    //     Type that this object will sort itself by.
    //
    //   TValue:
    //     The type of the value.
    [DebuggerDisplay("SortedBy = {_sort_by}, Value = {_value}")]
    public struct SortablePair<TSortBy, TValue>
        : IComparable<SortablePair<TSortBy, TValue>>
        where TSortBy : IComparable
    {
        public SortablePair(TSortBy sort_by, TValue value)
        {
            _sort_by = sort_by;
            _value = value;
        }
        public int CompareTo(SortablePair<TSortBy, TValue> other)
        {
            return _sort_by.CompareTo(other._sort_by);
        }
        public TSortBy SortBy
        {
            get
            {
                return _sort_by;
            }
        }
        public TValue Value
        {
            get
            {
                return _value;
            }
        }

        private TSortBy _sort_by;
        private TValue _value;
    }

    // Summary:
    //     An alternative to System.Collections.Generic.SortedList that can 
    //     contain a collection of SortablePairs. Unlike SortedList this 
    //     collection allows duplicate SortBy attributes.
    //
    // Type parameters:
    //   TSort:
    //     Type that the collection will sort itself by.
    //
    //   TValue:
    //     The type of values in the collection.
    public class AutoSortList<TSort, TValue> 
        : IEnumerable<SortablePair<TSort, TValue>>, IEnumerable
        where TSort : IComparable
    {
        public AutoSortList()
        {
            _list = new List<SortablePair<TSort, TValue>>();
        }
        public AutoSortList(IEnumerable<SortablePair<TSort, TValue>> collection)
        {
            _list = new List<SortablePair<TSort, TValue>>(collection);
            _list.Sort();
        }
        public AutoSortList(int capacity)
        {
            _list = new List<SortablePair<TSort, TValue>>(capacity);
        }
        public IEnumerator<SortablePair<TSort, TValue>> GetEnumerator()
        {
            return _list.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _list.GetEnumerator();
        }
        public IList<TValue> Values
        {
            get
            {
                List<TValue> values = new List<TValue>();
                foreach (SortablePair<TSort, TValue> pair in _list)
                {
                    values.Add(pair.Value);
                }

                return values;
            }
        }
        public void Add(TSort sort_by, TValue item)
        {
            _list.Add(new SortablePair<TSort, TValue>(sort_by, item));
            _list.Sort();
        }
        public void AddRange(IEnumerable<SortablePair<TSort, TValue>> collection)
        {
            _list.AddRange(collection);
            _list.Sort();
        }
        public SortablePair<TSort, TValue> this[int index]
        {
            get
            {
                return _list[index];
            }
        }
        public int Count
        {
            get
            {
                return _list.Count;
            }
        }
        public void Clear()
        {
            _list.Clear();
        }

        private List<SortablePair<TSort, TValue>> _list;
    }
}